\subsection{Análise Semântica}

Fazer a restrição sobre a linguagem, como comentado anteriormente, nos
permitiu realizar mais checagens de erros semânticos no código, sem necessitar
da execução. As checagens semânticas de nosso analisador são explicadas a
seguir.

\subsubsection{Acesso a variáveis}

Essa checagem também foi implementada para a linguagem sem a restrição,
explicado na seção \ref{sec:boaformacao}. Só é permitido o acesso a variáveis
que tenham sido anteriormente declaradas em seu escopo. Blocos como \verb#if#,
\verb#for# e \verb#while# não modificam o escopo, sendo possível o acesso
dentro do bloco a variáveis definidas antes do bloco, e também o acesso depois
do bloco a variáveis definidas dentro dele. O único modificador de escopo é a
declaração de função, e as variáveis são de escopo local, não sendo permitido o
acesso a variáveis definidas fora da função, e o acesso fora da função a
variáveis definidas dentro dela.

A seção \ref{sec:boaformacao} apresenta exemplos de trechos de código que
ilustram a checagem.

\subsubsection{Declarações de funções aninhadas}

Essa checagem implementa a restrição que fizemos sobre PHP. Não é permitido que
uma função seja declarada dentro do bloco de uma outra função, sendo apontado o
erro semântico.

\begin{lstlisting}[frame=single,
caption={Declaração aninhada de funções},label=lst:declaracaoAninhada,
numbers=left, breaklines=true, language=PHP, extendedchars=true, literate={á}{{\'a}}1 {ã}{{\~a}}1 {é}{{\'e}}1 {ç}{{\c{c}}}1 {Ç}{{\c{C}}}1 {ó}{{\'o}}1 {í}{{\'i}}1 {à}{{'a}}1 {õ}{{\~o}}1, showstringspaces=false, showspaces=false, morekeywords={}] 
<?php 
function a() {
	function b() {
		echo 'b';
	}
	echo 'a';
}
?>
\end{lstlisting}

No exemplo \ref{lst:declaracaoAninhada}, o analisador encontra a declaração da
função \verb#b()# dentro da declaração da função \verb#a()# e aponta erro. O
mesmo comportamento acontece para quantas forem as declarações aninhadas, em
quantos níveis forem. No exemplo \ref{lst:muitasAninhadas}, cada uma das
declarações das funções \verb#b()#, \verb#c()# e \verb#d()# gerará um erro
semântico, mas não a declaração da função \verb#e()#.

\begin{lstlisting}[frame=single,
caption={Declaração aninhada de funções},label=lst:muitasAninhadas,
numbers=left, breaklines=true, language=PHP, extendedchars=true, literate={á}{{\'a}}1 {ã}{{\~a}}1 {é}{{\'e}}1 {ç}{{\c{c}}}1 {Ç}{{\c{C}}}1 {ó}{{\'o}}1 {í}{{\'i}}1 {à}{{'a}}1 {õ}{{\~o}}1, showstringspaces=false, showspaces=false, morekeywords={}] 
<?php 
function a() {
	function b() {
		echo 'b';
		function c() {
			echo 'c';
		}
	}
	function d() {
		echo 'd';
	}
	echo 'a';
}
function e() {
	echo 'e';
}
?>
\end{lstlisting}

\subsubsection{Funções com o mesmo nome}

Como já abordado, PHP não dá suporte a sobrecarga de funções. Não é permitido
que funções sejam declaradas com o mesmo nome, não importando o número de
parâmetros de cada. Ou seja, não é possível a declaração de uma função que
recebe um parâmetro e outra que recebe dois, se ambas possuem o mesmo nome.

Sem a restrição que propomos, essa checagem só é feita na execução do código,
pois o \emph{bind} só é feito no momento da chamada da função.

\begin{lstlisting}[frame=single,
caption={Declaração de função com o mesmo nome},label=lst:funcaoRepetida,
numbers=left, breaklines=true, language=PHP, extendedchars=true, literate={á}{{\'a}}1 {ã}{{\~a}}1 {é}{{\'e}}1 {ç}{{\c{c}}}1 {Ç}{{\c{C}}}1 {ó}{{\'o}}1 {í}{{\'i}}1 {à}{{'a}}1 {õ}{{\~o}}1, showstringspaces=false, showspaces=false, morekeywords={}] 
<?php 
function a() {
	echo 1;
}
function b() {
	function a() {
		echo 2;
	}
}
if ($expressao) {
	b();
}
?>
\end{lstlisting}

O exemplo \ref{lst:funcaoRepetida} ilutra a impossibilidade de tratarmos a
declaração de funções com o mesmo nome se não fizermos a restrição à
linguagem proposta. Inicialmente, esse código não mostraria nenhum erro. Porém,
se o valor booleano de \verb#$expressao# na linha 10 for verdadeiro, a função
\verb#b()# será invocada na linha 11, tentará fazer a declaração da função
\verb#a()# na linha 6, porém já foi declarada uma função com esse nome na linha
1, sendo então lançado o erro. Fica claro então que, se não houver a restrição
de não ser permitido a declaração de funções aninhadas, torna-se impossível essa
checagem se não for em tempo de execução.

Porém, como fizemos essa restrição, nosso interpretador lança o erro semântico
caso funções sejam declaradas com o mesmo nome, como podemos ver no exemplo
\ref{lst:funcaoRepetida2}.

\begin{lstlisting}[frame=single,
caption={Declaração de função com o mesmo nome},label=lst:funcaoRepetida2,
numbers=left, breaklines=true, language=PHP, extendedchars=true, literate={á}{{\'a}}1 {ã}{{\~a}}1 {é}{{\'e}}1 {ç}{{\c{c}}}1 {Ç}{{\c{C}}}1 {ó}{{\'o}}1 {í}{{\'i}}1 {à}{{'a}}1 {õ}{{\~o}}1, showstringspaces=false, showspaces=false, morekeywords={}] 
<?php 
function a() {
	echo 1;
}
function a() {	// erro semantico
	echo 2;
}
?>
\end{lstlisting}